<!DOCTYPE html>
<html lang="en">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>SPARC ABI Changes in GCC 3.4</title>
<link rel="stylesheet" type="text/css" href="https://gcc.gnu.org/gcc.css" />
</head>

<body>

<h1>SPARC ABI Changes in GCC 3.4</h1>

<p>GCC 3.4 fixes several cases in which earlier releases would not
   follow the SPARC calling conventions.  This document describes
   each fix and the kind of code it will affect.  In each case,
   GCC 3.4 will not be binary compatible with earlier releases.</p>

<p>Most of the fixes are related to the handling of small structure
   and union types in 64-bit mode.</p>

<h2>A. Small structure arguments and return values (1)</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABI</th>
    <td>64-bit</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>A small structure is passed or returned in a register; and</li>
	  <li>it contains a unique field of type <code>float</code> .</li>
	</ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The register was odd-numbered.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The register is even-numbered.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>struct s { float f; };
void g (struct s x);</pre>

	<p><code>x</code> is passed in floating-point register <code>%f0</code>,
	   instead of <code>%f1</code>.</p></td>
  </tr>
</table>

<h2>B. Small structure arguments and return values (2)</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABI</th>
    <td>64-bit</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>A small structure is passed or returned in registers;</li>
	  <li>its size in bytes is not a multiple of 8 and is greater than 8;</li>
	  <li>its last field is of integral type; and</li>
	  <li>its last but one field is smaller than a word.</li>
	</ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The last used register was padded at the most significant end.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The last used register is padded at the least significant end.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>struct s { float f; int i; int j; };
void g (struct s x);</pre>

	<p><code>x</code> is passed in several registers, which are laid
	    out as follows:</p>

	<table class="padding5">
	  <tr class="center">
	  <th></th>
	  <th>%f0</th> <th>%o0 (high)</th> <th>%o0 (low)</th>
	  <th>%o1 (high)</th> <th>%o1 (low)</th>
	  </tr>

	  <tr class="center">
	  <th class="left">Old&nbsp;behavior</th>
	  <td>f</td> <td>padding</td> <td>i</td>
	  <td>padding</td> <td>j</td>
	  </tr>

	  <tr class="center">
	  <th class="left">New&nbsp;behavior</th>
	  <td>f</td> <td>padding</td> <td>i</td>
	  <td>j</td> <td>padding</td>
	  </tr>
	</table></td>
  </tr>
</table>

<h2>C. Small unions arguments and return values</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABI</th>
    <td>64-bit</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>A small union is passed or returned in a register; and</li>
	  <li>its size in bytes is less than 8.</li>
	</ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The register was padded at the most significant end.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The register is padded at the least significant end.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>union u { int i; float f; };
void g (union u x);</pre>

	<p><code>x</code> is passed in register <code>%o0</code>, which is
	   laid out as follows:</p>

	<table class="padding5">
	  <tr class="center">
	  <th></th>
	  <th>%o0 (high)</th> <th>%o0 (low)</th>
	  </tr>

	  <tr class="center">
	  <th class="left">Old&nbsp;behavior</th>
	  <td>padding</td> <td>i/f</td>
	  </tr>

	  <tr class="center">
	  <th class="left">New&nbsp;behavior</th>
	  <td>i/f</td> <td>padding</td>
	  </tr>
	</table></td>
  </tr>
</table>

<h2>D. Small structure arguments (1)</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABI</th>
    <td>64-bit</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>A small structure is passed past the 6th argument slot and
	      prior to the last one; and</li>
	  <li>it contains a complex floating-point field.</li>
	</ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The complex floating-point field was passed on the stack.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The complex floating-point field is passed in registers.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>struct s { _Complex float cf; };
void g (struct s x1, struct s x2, struct s x3, struct s x4, struct s x5, struct s x6, struct s x7);</pre>

	<p><code>x7</code> is passed in floating-point registers <code>%f12-%f13</code>,
	   instead of on the stack.</p></td>
  </tr>
</table>

<h2>E. Small structure arguments (2)</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABI</th>
    <td>64-bit</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>A small structure is passed past the 6th argument slot and
	      prior to the last one;</li>
	  <li>it contains a nested structure; and</li>
	  <li>the nested structure contains a floating-point field.</li>
	</ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The floating-point field was passed on the stack.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The floating-point field is passed in registers.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>struct s { struct { double d; } ns; };
void g (struct s x1, struct s x2, struct s x3, struct s x4, struct s x5, struct s x6, struct s x7);</pre>

	<p><code>x7</code> is passed in floating-point registers <code>%f12-%f13</code>,
	   instead of on the stack.</p></td>
  </tr>
</table>

<h2>F. Complex floating-point arguments and return values</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABI</th>
    <td>32-bit</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td>A complex floating-point value is passed to or returned from a
	function.</td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The complex floating-point value was passed or returned according
	to the following table:

        <table class="padding5">
	  <tr class="center">
	  <th></th>
	  <th>argument</th> <th>return&nbsp;value</th>
	  </tr>

	  <tr class="center">
	  <th class="left">_Complex float</th>
	  <td>integer registers</td> <td>integer registers</td>
	  </tr>

	  <tr class="center">
	  <th class="left">_Complex double</th>
	  <td>integer registers</td> <td>integer registers</td>
	  </tr>

	  <tr class="center">
	  <th class="left">_Complex long double</th>
	  <td>memory</td> <td>memory</td>
	  </tr>
	</table></td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The complex floating-point value is passed or returned according
	to the following table:

	<table class="padding5">
	  <tr class="center">
	  <th></th>
	  <th>argument</th> <th>return&nbsp;value</th>
	  </tr>

	  <tr class="center">
	  <th class="left">_Complex float</th>
	  <td>memory</td> <td>floating-point registers</td>
	  </tr>

	  <tr class="center">
	  <th class="left">_Complex double</th>
	  <td>memory</td> <td>floating-point registers</td>
	  </tr>

	  <tr class="center">
	  <th class="left">_Complex long double</th>
	  <td>memory</td> <td>floating-point registers</td>
	  </tr>
	</table></td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>_Complex float g (void);</pre>

	<p>The return value is returned in floating-point registers <code>%f0-%f1</code>,
	   instead of registers <code>%o0-%o1</code>.</p></td>
  </tr>
</table>

<h2>G. TI mode integral arguments (GCC extension)</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABI</th>
    <td>64-bit</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td>A TI mode integral value is passed to a function.</td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The TI mode integral value was not aligned on a 16-byte boundary in
	the parameter array.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The TI mode integral value is aligned on a 16-byte boundary in
	the parameter array.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>typedef int TItype __attribute__ ((mode (TI)));
void g (int x1, TItype x2);</pre>

        <p><code>x2</code> is passed in registers <code>%o2-%o3</code>, instead
	    of <code>%o1-%o2</code>.</p></td>
  </tr>
</table>

<h2>H. Complex integral arguments (GCC extension) (1)</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABI</th>
    <td>32-bit</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td>A <code>_Complex long long</code> value is passed to a function.</td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The <code>_Complex long long</code> value was passed in registers.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The <code>_Complex long long</code> value is passed in memory.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>void g (_Complex long long x1);</pre>

        <p><code>x1</code> (its address) is passed in register <code>%o0</code>,
	   instead of <code>%o0-%o3</code>.</p></td>
  </tr>
</table>

<h2>I. Complex integral arguments (GCC extension) (2)</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABI</th>
    <td>64-bit</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td>A complex integral value is passed in registers.</td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>Two consecutive registers were reserved, regardless of the size of
        the complex integral value.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>Only one register is reserved if the complex integral value can fit
        in a single register.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>void g (_Complex int x1, _Complex int x2);</pre>

        <p><code>x2</code> is passed in register <code>%o1</code>, instead
	    of <code>%o2</code>.</p></td>
  </tr>
</table>

</body>
</html>
